#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "abb.h"

void print_test(char* name, bool result)
{
    printf("%s: %s\n", name, result? "OK" : "ERROR");
}

void Prueba_arbol()
{
	char *clave1 = "perro", *valor1 = "guau";
	char *clave2 = "gato", *valor2 = "miau";
	char *clave3 = "vaca", *valor3 = "mu";
	abb_t* arbol = abb_crear(strcmp,NULL);
	
	
	print_test("Prueba arbol crear arbol vacio", arbol);
	print_test("Prueba arbol la cantidad de elementos es 0", abb_cantidad(arbol) == 0);
	print_test("Prueba arbol obtener clave A, es NULL, no existe", !abb_obtener(arbol, "A"));
	print_test("Prueba arbol pertenece clave A, es false, no existe", !abb_pertenece(arbol, "A"));
	print_test("Prueba arbol borrar clave A, es NULL, no existe", !abb_borrar(arbol, "A"));
	
	abb_iter_t* iter = abb_iter_in_crear(arbol);
	print_test("Prueba arbol iter crear iterador arbol vacio", iter);
	print_test("Prueba arbol iter esta al final", abb_iter_in_al_final(iter));
	print_test("Prueba arbol iter avanzar es false", !abb_iter_in_avanzar(iter));
	print_test("Prueba arbol iter ver actual es NULL", !abb_iter_in_ver_actual(iter));
	
	

	/* Inserta 1 valor y luego lo borra */
	print_test("Prueba arbol insertar clave1", abb_guardar(arbol, clave1, valor1));
	print_test("Prueba arbol la cantidad de elementos es 1", abb_cantidad(arbol) == 1);
	print_test("Prueba arbol obtener clave1 es valor1", abb_obtener(arbol, clave1) == valor1);
	print_test("Prueba arbol pertenece clave1, es true", abb_pertenece(arbol, clave1));

	print_test("Prueba arbol insertar clave2", abb_guardar(arbol, clave2, valor2));
	print_test("Prueba arbol la cantidad de elementos es 2", abb_cantidad(arbol) == 2);
	print_test("Prueba arbol obtener clave2 es valor2", abb_obtener(arbol, clave2) == valor2);
	print_test("Prueba arbol pertenece clave2, es true", abb_pertenece(arbol, clave2));

	print_test("Prueba arbol insertar clave3", abb_guardar(arbol, clave3, valor3));
	print_test("Prueba arbol la cantidad de elementos es 3", abb_cantidad(arbol) == 3);
	print_test("Prueba arbol obtener clave3 es valor3", abb_obtener(arbol, clave3) == valor3);
	print_test("Prueba arbol pertenece clave3, es true", abb_pertenece(arbol, clave3));
	/* Al borrar cada elemento comprueba que ya no está pero los otros sí. */
	print_test("Prueba arbol pertenece clave3, es verdadero", abb_pertenece(arbol, clave3));
	print_test("Prueba arbol borrar clave3, es valor3", abb_borrar(arbol, clave3) == valor3);
	print_test("Prueba arbol borrar clave3, es NULL", !abb_borrar(arbol, clave3));
	print_test("Prueba arbol pertenece clave3, es falso", !abb_pertenece(arbol, clave3));
	print_test("Prueba arbol obtener clave3, es NULL", !abb_obtener(arbol, clave3));
	print_test("Prueba arbol la cantidad de elementos es 2", abb_cantidad(arbol) == 2);

	print_test("Prueba arbol pertenece clave1, es verdadero", abb_pertenece(arbol, clave1));
	print_test("Prueba arbol borrar clave1, es valor1", abb_borrar(arbol, clave1) == valor1);
	print_test("Prueba arbol borrar clave1, es NULL", !abb_borrar(arbol, clave3));
	print_test("Prueba arbol pertenece clave1, es falso", !abb_pertenece(arbol, clave1));
	print_test("Prueba arbol obtener clave1, es NULL", !abb_obtener(arbol, clave1));
	print_test("Prueba arbol la cantidad de elementos es 1", abb_cantidad(arbol) == 1);

	print_test("Prueba arbol pertenece clave2, es verdadero", abb_pertenece(arbol, clave2));
	print_test("Prueba arbol borrar clave2, es valor2", abb_borrar(arbol, clave2) == valor2);
	print_test("Prueba arbol borrar clave2, es NULL", !abb_borrar(arbol, clave3));
	print_test("Prueba arbol pertenece clave2, es falso", !abb_pertenece(arbol, clave2));
	print_test("Prueba arbol obtener clave2, es NULL", !abb_obtener(arbol, clave2));
	print_test("Prueba arbol la cantidad de elementos es 0", abb_cantidad(arbol) == 0);
	
	
	
	abb_iter_in_destruir(iter);
	abb_destruir(arbol);
	
}

void prueba_arbol_iterar_volumen(size_t largo)
{
	abb_t* arbol = abb_crear(strcmp,NULL);

	const size_t largo_clave = 10;
	char (*claves)[largo_clave] = malloc(largo * largo_clave);

	int valores[largo];

	/* Inserta 'largo' parejas en el hash */
	bool ok = true;
	int i;
	for (i = 0; i < largo; i++) {
		sprintf(claves[i], "%08d", i);
		valores[i] = i;
		ok = abb_guardar(arbol, claves[i], &valores[i]);
		if (!ok) break;
	}
	print_test("Prueba arbol cantidad 300", abb_cantidad(arbol)==300);

	// Prueba de iteración sobre las claves almacenadas.
	abb_iter_t* iter = abb_iter_in_crear(arbol);
	print_test("Prueba arbol iterador esta al final, es false", !abb_iter_in_al_final(iter));

	ok = true;
	int j;
	const char *clave;
	int *valor;
	
	for (j = 0; j < largo; j++) {
		if ( abb_iter_in_al_final(iter) ) {
			ok = false;
			break;
		}
		clave = abb_iter_in_ver_actual(iter);
		if ( clave == NULL ) {
			ok = false;
			break;
		}
		valor = abb_obtener(arbol, clave);
		if ( valor == NULL ) {
			ok = false;
			break;
		}
		*valor = largo;
		abb_iter_in_avanzar(iter);
	}
	print_test("Prueba arbol iteración en volumen", ok);
	print_test("Prueba arbol iteración en volumen, recorrio todo el largo", j == largo);
	if (i != largo) printf("Largo recorrido: %d\n", j);
	print_test("Prueba arbol iterador esta al final, es verdadero", abb_iter_in_al_final(iter));
	print_test("Prueba arbol iterador esta al final, es verdadero", abb_cantidad(arbol)==300);
	
	

	free(claves);
	abb_iter_in_destruir(iter);
	abb_destruir(arbol);
}

int main (){
	Prueba_arbol();
	prueba_arbol_iterar_volumen(300);
	return 0;
}
